package com.mes_for_xxxxxx.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mes_for_xxxxxx.context.BaseContext;
import com.mes_for_xxxxxx.entity.Employee;
import com.mes_for_xxxxxx.entity.Process;
import com.mes_for_xxxxxx.entity.Processflow;
import com.mes_for_xxxxxx.entity.dto.ProcessflowDTO;
import com.mes_for_xxxxxx.entity.dto.ReceiveProcessflowDTO;
import com.mes_for_xxxxxx.enums.StatusEnums;
import com.mes_for_xxxxxx.mapper.ProcessMapper;
import com.mes_for_xxxxxx.mapper.ProcessflowMapper;
import com.mes_for_xxxxxx.service.IEmployeeService;
import com.mes_for_xxxxxx.service.IProcessService;
import com.mes_for_xxxxxx.service.IProcessflowService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

/**
 * <p>
 * 工艺流程表 服务实现类
 * </p>
 *
 * @author 179005
 * @since 2024-09-10
 */
@Service
public class ProcessflowServiceImpl extends ServiceImpl<ProcessflowMapper, Processflow> implements IProcessflowService {

    @Autowired
    IProcessService processService;
    @Autowired
    IEmployeeService employeeService;

    @Override
    public List<Processflow> outTimeTask() {
        return baseMapper.outTimeTask();
    }
    @Override
    public void delayProcessflow(String orderId) {
        baseMapper.delayProcessflow(orderId);
    }

    @Override
    public int pushStatusProcessflow(String orderId) {
        QueryWrapper<Processflow> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);
        Processflow processflow = baseMapper.selectOne(queryWrapper);
        Integer status = processflow.getStatus();
        // 1.status需要到下一阶段
        if (StatusEnums.NOT_START.getCode().equals(status)) {
            processflow.setStatus(StatusEnums.NOT_COMPLETED.getCode());
        } else if (StatusEnums.NOT_COMPLETED.getCode().equals(status)) {
            processflow.setStatus(StatusEnums.NOT_TESTING.getCode());
        } else if (StatusEnums.NOT_TESTING.getCode().equals(status)) {
            processflow.setStatus(StatusEnums.NOT_SEND.getCode());
        } else {
            // 2.需要进入下一交接人手中
            return -1;
        }
        String thisFlow = processflow.getThisFlow();
        String routeNumber = processflow.getRouteNumber();
        Process process = getProcess(routeNumber, thisFlow);
        Double needMaxTime = process.getNeedMaxTime();
        processflow.setEndTime(LocalDateTime.now().plusHours(needMaxTime.intValue()));
        baseMapper.updateById(processflow);
        return 0;

    }


    @Override
    @Transactional
    public void pushProcessflow(ProcessflowDTO dto) {
        //将当前工序状态改为已交接并提交
        QueryWrapper<Processflow> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", dto.getOrderId());
        Processflow oldProcessflow = baseMapper.selectOne(queryWrapper);
        Integer status = oldProcessflow.getStatus();
        if (!StatusEnums.NOT_SEND.getCode().equals(status)) {
            throw new RuntimeException("工序流转失败，当前状态不允许流转至下一道工序");
        }
        oldProcessflow.setStatus(StatusEnums.HANDOVER.getCode());
        baseMapper.updateById(oldProcessflow);

        //生成新的工序
        String nextFlow = dto.getNextNextFlow();
        String nextRoomCode = dto.getNextRoomCode();
        String thisFlow = oldProcessflow.getNextFlow();
        String thisWorker = BaseContext.getCurrentId().toString();
        Processflow processflow = new Processflow();
        processflow.setStatus(StatusEnums.NOT_START.getCode());
        processflow.setNextRoomCode(nextRoomCode);
        processflow.setRouteNumber(oldProcessflow.getRouteNumber());
        processflow.setOrderId(setOrderId(oldProcessflow.getRouteNumber(), thisFlow));
        processflow.setProductId(oldProcessflow.getProductId());
        processflow.setProductName(oldProcessflow.getProductName());
        processflow.setThisFlow(thisFlow);
        processflow.setWorker(thisWorker);
        processflow.setNextFlow(nextFlow);
        processflow.setEquipment(dto.getNextEquipment());
        processflow.setStartTime(LocalDateTime.now());
        processflow.setEndTime(LocalDateTime.now().plusHours(24));
        Integer materiralNumber = oldProcessflow.getMaterialNumber();
        Double yield = oldProcessflow.getYield();
        processflow.setMaterialNumber(materiralNumber * yield.intValue());

        processflow.setYield(yield);
        int insert = baseMapper.insert(processflow);
        if (insert < 1) {
            throw new RuntimeException("工序流转失败，请您认真填写表信息");
        }
    }

    @Override
    @Transactional
    public Processflow add(Processflow processflow) {
        processflow.setCreatedAt(LocalDateTime.now());
        processflow.setUpdatedAt(LocalDateTime.now());

        processflow.setStatus(StatusEnums.NOT_START.getCode());
        processflow.setStartTime(LocalDateTime.now());
        String thisFlow = processflow.getThisFlow();
        String routeNumber = processflow.getRouteNumber();

        Process process = this.getProcess(routeNumber, thisFlow);

        Double needMaxTime = process.getNeedMaxTime();
        Double yield = process.getYield();

        processflow.setEndTime(LocalDateTime.now().plusHours(needMaxTime.intValue()));
        processflow.setYield(yield);
        processflow.setOrderId(setOrderId(processflow.getRouteNumber(), processflow.getThisFlow()));
        processflow.setProductId(setProductId(processflow.getProductId()));
        //processflow.setWorker("1");
        if(BaseContext.getCurrentId() == null){
            processflow.setWorker("123");
        }else{
            Long currentId = BaseContext.getCurrentId();
            Employee employee = employeeService.getById(currentId);
            String name = employee.getName();
            processflow.setWorker(name);
        }
        baseMapper.insert(processflow);
        return processflow;
    }

    @Override
    public void testOrder(String orderId, Integer firstMaterial) {
        QueryWrapper<Processflow> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);
        Processflow processflow = baseMapper.selectOne(queryWrapper);
        Double yield = processflow.getYield();
        Integer materialNumber = processflow.getMaterialNumber();
        Integer currMaterial = (int) (yield * materialNumber);
        double var = Math.round(firstMaterial / (double) currMaterial);
        processflow.setFirstMaterial(firstMaterial);
        processflow.setCurrYield(var);
        processflow.setStatus(StatusEnums.NOT_SEND.getCode());
        baseMapper.updateById(processflow);
    }

    @Override
    public int addNextFlow() {
        QueryWrapper<Processflow> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNull("next_flow");
        List<Processflow> processflows = baseMapper.selectList(queryWrapper);
        List<Process> processList = processService.list();

//        ConcurrentMap<String, String> map = processList.stream().collect(Collectors.toConcurrentMap(
//                Process::getProduceName,
//                Process::getNextProduce
//        ));
        HashMap<String, String> map = new HashMap<>();
        processList.forEach(
                process -> {
                    map.put(process.getProduceName(), process.getNextProduce());
                }
        );
        int i = 0;
        for (Processflow processflow : processflows) {
            String thisFlow = processflow.getThisFlow();
            String nextFlow = map.get(thisFlow);
            if (nextFlow != null) {
                processflow.setNextFlow(nextFlow);
                baseMapper.updateById(processflow);
                i++;
            }
        }
        return i;
    }

    @Override
    @Transactional
    public void receive(ReceiveProcessflowDTO dto) {
        String orderId = dto.getOrderId();
        String equipment = dto.getEquipment();
        Integer secondMaterial = dto.getSecondMaterial();
        String nextRoomCode = dto.getNextRoomCode();
        String routeNumber = dto.getRouteNumber();

        QueryWrapper<Processflow> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);
        Processflow processflow = baseMapper.selectOne(queryWrapper);
        //processflow.setNextWorker("124");
        processflow.setSecondMaterial(secondMaterial);
        processflow.setStatus(StatusEnums.HANDOVER.getCode());
        baseMapper.updateById(processflow);
        Processflow thisProcessflow = new Processflow();
        thisProcessflow.setNextRoomCode(nextRoomCode);
        thisProcessflow.setEquipment(equipment);
        thisProcessflow.setProductName(processflow.getProductName());
        thisProcessflow.setThisFlow(processflow.getNextFlow());
        thisProcessflow.setRouteNumber(routeNumber);
        thisProcessflow.setMaterialNumber((int) (processflow.getMaterialNumber() * processflow.getYield()));

        add(thisProcessflow);
    }

    @Override
    public List<Processflow> accept(Integer id) {
        Employee employee = employeeService.getById(id);
        String roomCode = employee.getRoomCode();
        QueryWrapper<Processflow> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("next_room_code",roomCode);
        queryWrapper.eq("status",-1);
        queryWrapper.last("limit 5");
        List<Processflow> list = this.list(queryWrapper);
        return list;
    }

    private Process getProcess(String routeNumber, String thisFlow) {
        return processService.getOne(new QueryWrapper<Process>().eq("route_id", routeNumber).eq("produce_Name", thisFlow));
    }

    private String setOrderId(String routerNumber, String thisFlow) {
        return routerNumber + "-" + thisFlow + "-" + UUID.randomUUID();
    }

    private String setProductId(String productId) {
        return UUID.randomUUID().toString();
    }
}
